1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.google.common.collect;
16
17 import static com.google.common.base.Preconditions.checkArgument;
18 import static com.google.common.base.Preconditions.checkNotNull;
19 import static com.google.common.collect.BoundType.CLOSED;
20
21 import com.google.common.annotations.GwtCompatible;
22
23 import java.util.Collection;
24
25 import javax.annotation.Nullable;
26
27
28
29
30
31
32 @GwtCompatible(emulated = true)
33 @SuppressWarnings("unchecked")
34 final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C> {
35 private final Range<C> range;
36
37 RegularContiguousSet(Range<C> range, DiscreteDomain<C> domain) {
38 super(domain);
39 this.range = range;
40 }
41
42 private ContiguousSet<C> intersectionInCurrentDomain(Range<C> other) {
43 return (range.isConnected(other))
44 ? ContiguousSet.create(range.intersection(other), domain)
45 : new EmptyContiguousSet<C>(domain);
46 }
47
48 @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
49 return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
50 }
51
52 @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
53 boolean toInclusive) {
54 if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
55
56 return new EmptyContiguousSet<C>(domain);
57 }
58 return intersectionInCurrentDomain(Range.range(
59 fromElement, BoundType.forBoolean(fromInclusive),
60 toElement, BoundType.forBoolean(toInclusive)));
61 }
62
63 @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
64 return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
65 }
66
67 @Override public UnmodifiableIterator<C> iterator() {
68 return new AbstractSequentialIterator<C>(first()) {
69 final C last = last();
70
71 @Override
72 protected C computeNext(C previous) {
73 return equalsOrThrow(previous, last) ? null : domain.next(previous);
74 }
75 };
76 }
77
78 private static boolean equalsOrThrow(Comparable<?> left, @Nullable Comparable<?> right) {
79 return right != null && Range.compareOrThrow(left, right) == 0;
80 }
81
82 @Override boolean isPartialView() {
83 return false;
84 }
85
86 @Override public C first() {
87 return range.lowerBound.leastValueAbove(domain);
88 }
89
90 @Override public C last() {
91 return range.upperBound.greatestValueBelow(domain);
92 }
93
94 @Override public int size() {
95 long distance = domain.distance(first(), last());
96 return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
97 }
98
99 @Override public boolean contains(@Nullable Object object) {
100 if (object == null) {
101 return false;
102 }
103 try {
104 return range.contains((C) object);
105 } catch (ClassCastException e) {
106 return false;
107 }
108 }
109
110 @Override public boolean containsAll(Collection<?> targets) {
111 return Collections2.containsAllImpl(this, targets);
112 }
113
114 @Override public boolean isEmpty() {
115 return false;
116 }
117
118 @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
119 checkNotNull(other);
120 checkArgument(this.domain.equals(other.domain));
121 if (other.isEmpty()) {
122 return other;
123 } else {
124 C lowerEndpoint = Ordering.natural().max(this.first(), other.first());
125 C upperEndpoint = Ordering.natural().min(this.last(), other.last());
126 return (lowerEndpoint.compareTo(upperEndpoint) < 0)
127 ? ContiguousSet.create(Range.closed(lowerEndpoint, upperEndpoint), domain)
128 : new EmptyContiguousSet<C>(domain);
129 }
130 }
131
132 @Override public Range<C> range() {
133 return range(CLOSED, CLOSED);
134 }
135
136 @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
137 return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
138 range.upperBound.withUpperBoundType(upperBoundType, domain));
139 }
140
141 @Override public boolean equals(@Nullable Object object) {
142 if (object == this) {
143 return true;
144 } else if (object instanceof RegularContiguousSet) {
145 RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
146 if (this.domain.equals(that.domain)) {
147 return this.first().equals(that.first())
148 && this.last().equals(that.last());
149 }
150 }
151 return super.equals(object);
152 }
153
154
155 @Override public int hashCode() {
156 return Sets.hashCodeImpl(this);
157 }
158
159 private static final long serialVersionUID = 0;
160 }
161